<template>
  <div id="app">
    <div :class="[mode===1||mode===3?'mode1':'','content']">
      <div class="abc">
        <div class="row" v-for="(row,x) in list" :key="x">
          <Item
            v-for="(item,y) in row"
            :key="y"
            :x="x"
            :y="y"
            :snake="snake"
            :appleCoordinate="apple"
            :hinder="hinder"
          />
        </div>
      </div>
    </div>
    <div class="aa">
      <h1>您的得分是：{{grade}}</h1>
      <div class="but">
        <el-button :disabled="isStart" type="primary" v-on:click="startGame" round>开始游戏</el-button>
        <el-button :disabled="mode===1" type="primary" v-on:click="changeMode(1)" round>经典模式</el-button>
        <el-button :disabled="mode===2" type="primary" v-on:click="changeMode(2)" round>无围墙模式</el-button>
        <el-button :disabled="mode===3" type="primary" v-on:click="changeMode(3)" round>迷宫模式</el-button>
      </div>
    </div>
  </div>
</template>

<script>
import { MessageBox } from "element-ui";
import Item from "./components/Item";
export default {
  name: "App",
  components: {
    Item
  },
  data() {
    return {
      isStart: false,
      list: [],
      // 键盘方向
      direction: "right",
      // 当前蛇的方向
      currentDirection: "right",
      snake: [[0, 2], [0, 1], [0, 0]],
      apple: [-1, -1],
      timer: null,
      mode: 1,
      hinder: []
    };
  },
  mounted() {
    const arr = new Array(20);
    const arr1 = Array.from(arr, () => [...arr]);
    this.list = arr1;
  },
  computed: {
    grade() {
      return (this.snake.length - 3) * 10;
    }
  },
  watch: {
    // 控制速度
    snake() {
      if (this.snake.length - 3 >= 5 && this.snake.length - 3 < 10) {
        clearInterval(this.timer);
        this.timer = setInterval(this.move, 200);
      } else if (this.snake.length - 3 >= 10 && this.snake.length - 3 < 15) {
        clearInterval(this.timer);
        this.timer = setInterval(this.move, 100);
      } else if (this.snake.length - 3 >= 15) {
        clearInterval(this.timer);
        this.timer = setInterval(this.move, 80);
      }
    }
  },
  methods: {
    // 移动函数
    move() {
      const arr1 = [...this.snake];
      arr1.unshift(arr1[0]);
      const x = arr1[0][0];
      const y = arr1[0][1];
      this.currentDirection = this.direction;
      switch (this.currentDirection) {
        case "right":
          arr1[0] = [x, y + 1];
          break;
        case "left":
          arr1[0] = [x, y - 1];
          break;
        case "top":
          arr1[0] = [x - 1, y];
          break;
        case "bottom":
          arr1[0] = [x + 1, y];
          break;
      }
      // 无围墙模式运动
      if (this.mode === 2) {
        if (arr1[0][0] >= 20) {
          arr1[0][0] = 0;
        } else if (arr1[0][0] < 0) {
          arr1[0][0] = 19;
        }
        if (arr1[0][1] >= 20) {
          arr1[0][1] = 0;
        } else if (arr1[0][1] < 0) {
          arr1[0][1] = 19;
        }
      }
      // 吃到苹果的情况
      if (arr1[0][0] === this.apple[0] && arr1[0][1] === this.apple[1]) {
        this.createApple();
      } else {
        arr1.pop();
      }

      this.snake = arr1;
      this.gameOver();
    },
    // 改变方向
    changeDirection() {
      document.addEventListener("keyup", e => {
        switch (e.keyCode) {
          case 37:
            if (this.currentDirection === "right") break;
            this.direction = "left";
            break;
          case 38:
            if (this.currentDirection === "bottom") break;
            this.direction = "top";
            break;
          case 39:
            if (this.currentDirection === "left") break;
            this.direction = "right";
            break;
          case 40:
            if (this.currentDirection === "top") break;
            this.direction = "bottom";
            break;
        }
      });
    },
    // 随机生成苹果
    createApple() {
      const x = Math.floor(Math.random() * 20);
      const y = Math.floor(Math.random() * 20);
      if (
        this.snake.some(item => item[0] === x && item[1] === y) ||
        (x === this.apple[0] && y === this.apple[1])
      ) {
        this.createApple();
      } else {
        if (
          this.mode === 3 &&
          this.hinder.some(item => item[0] === x && item[1] === y)
        ) {
          this.createApple();
        } else {
          this.apple = [x, y];
        }
      }
    },
    // 游戏结束条件
    gameOver() {
      const x = this.snake[0][0];
      const y = this.snake[0][1];
      // 撞墙
      if ((x < 0 || x > 19 || y < 0 || y > 19) && this.mode !== 2) {
        const result = MessageBox.alert(
          `你的分数是${this.grade}`,
          "game over",
          {
            confirmButtonText: "确定"
          }
        );
        this.initializationGame();
      }
      // 吃到自己
      if (
        this.snake.some(
          (item, index) => index !== 0 && item[0] === x && item[1] === y
        )
      ) {
        const result = MessageBox.alert(
          `你的分数是${this.grade}`,
          "game over",
          {
            confirmButtonText: "确定"
          }
        );
        this.initializationGame();
      }
      // 碰到围墙
      if (this.mode === 3) {
        if (this.hinder.some(item => item[0] === x && item[1] === y)) {
          const result = MessageBox.alert(
            `你的分数是${this.grade}`,
            "game over",
            {
              confirmButtonText: "确定"
            }
          );
          this.initializationGame();
        }
      }
    },
    // 创建阻碍物
    createHinder() {
      while (this.hinder.length < 20) {
        const x = Math.floor(Math.random() * 20);
        const y = Math.floor(Math.random() * 20);
        if (x <= 5 && y <= 3) continue;
        this.hinder.push([x, y]);
      }
    },
    // 初始化游戏
    initializationGame() {
      this.snake = [[0, 2], [0, 1], [0, 0]];
      this.direction = "right";
      clearInterval(this.timer);
      document.removeEventListener("keyup", e => {
        console.log(e.keyCode);
        switch (e.keyCode) {
          case 37:
            if (this.currentDirection === "right") break;
            this.direction = "left";
            break;
          case 38:
            if (this.currentDirection === "bottom") break;
            this.direction = "top";
            break;
          case 39:
            if (this.currentDirection === "left") break;
            this.direction = "right";
            break;
          case 40:
            if (this.currentDirection === "top") break;
            this.direction = "bottom";
            break;
        }
      });
      this.apple = [];
      this.isStart = false;
      this.hinder = [];
    },
    // 开始游戏
    startGame() {
      this.timer = setInterval(this.move, 250);
      this.changeDirection();
      this.isStart = true;
      if (this.mode === 3) this.createHinder();
      this.createApple();
    },
    // 改变模式
    changeMode(e) {
      this.mode = e;
      this.initializationGame();
    }
  }
};
</script>

<style>
.row {
  display: flex;
  width: 400px;
  background: rgb(211, 211, 211);
}
.content {
  width: 400px;
  padding: 20px;
}
.mode1 {
  background: #000;
}
#app {
  display: flex;
  justify-content: center;
}
.aa {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
}
</style>
